package com.alibaba.citrus.cr.sales.plan.facade.msg;

import com.alibaba.acm.shaded.com.alibaba.metrics.StringUtils;
import com.alibaba.acm.shaded.com.google.common.collect.Maps;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.constant.OrganizationConstants;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.sales.plan.api.setting.SalesPlanScItemWriteService;
import com.alibaba.citrus.cr.sales.plan.contants.SalesPlanConstants;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.BatchEditCostInsuranceFreightRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanScItemImportRequest;
import com.alibaba.citrus.cr.sales.plan.dto.api.request.SalesPlanScItemPageQueryRequest;
import com.alibaba.citrus.cr.sales.plan.facade.service.SalesPlanOutCommonService;
import com.alibaba.citrus.cr.sales.plan.repository.SalesPlanScItemRepository;
import com.alibaba.citrus.cr.sales.plan.sdo.SalesPlanScItemSDO;
import com.alibaba.citrus.cr.sales.plan.msg.SalesPlanScItemMessageConsumer;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.middleware.cache.runtime.service.EpochCacheService;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.epoch.app.bcorder.contants.BcOrderConstants;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByCodes2Response;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByIds2Request;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByIds2Response;
import com.epoch.app.bcorder.model.dto.BaselineGetOrganizationByTypeRequest;
import com.epoch.app.bcorder.model.dto.BatchQueryCompany2Request;
import com.epoch.app.bcorder.model.dto.CompanySDO;
import com.epoch.app.bcorder.model.dto.OrganizationSDO;
import com.epoch.app.bcorder.model.dto.ScItemSDO;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.BcOrderService;
import com.epoch.app.crplatformenhance.api.customersalescopequery.service.CustomerSaleScopeQueryService;
import com.epoch.app.crplatformenhance.api.organizationquery.dto.BatchQuerySuperiorSalesOrganizationRequest;
import com.epoch.app.crplatformenhance.api.organizationquery.dto.GetOrganizationByTypeRequest;
import com.epoch.app.crplatformenhance.api.organizationquery.dto.GetOrganizationByTypeResponse;
import com.epoch.app.crplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.crplatformenhance.dto.request.IdQueryRequest;
import com.epoch.app.crplatformenhance.dto.request.QuerySaleScopeRequest;
import com.epoch.app.crplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.crplatformenhance.model.dto.QuerySuperiorSalesOrganizationResponse;
import com.epoch.app.crplatformenhance.sdo.CustomerSaleScopeSDO;
import com.epoch.app.crpricecenter.api.pricequery.service.PriceQueryService;
import com.epoch.app.crpricecenter.dto.request.DimensionPropertyInfoRequest;
import com.epoch.app.crpricecenter.dto.request.HumanInfoRequest;
import com.epoch.app.crpricecenter.dto.request.MaterialInfoRequest;
import com.epoch.app.crpricecenter.dto.request.PlaceInfoRequest;
import com.epoch.app.crpricecenter.dto.request.PriceQueryRequest;
import com.epoch.app.crpricecenter.dto.response.ItemPriceResponse;
import com.epoch.app.crpricecenter.dto.response.PriceQueryResponse;
import com.epoch.app.crpricecenter.model.enums.PriceTypeEnum;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 计划货品范围价格更新处理
 * @author suqing.tjf
 * @date 2022年01月06日16:37:57
 */
@Component
public class SalesPlanScItemMessageConsumerImpl implements SalesPlanScItemMessageConsumer {

    private final Log log = Log.getLogger(SalesPlanScItemMessageConsumerImpl.class);

    @Resource
    private SalesPlanScItemRepository salesPlanScItemRepository;

    @Autowired(required = false)
    private PriceQueryService priceQueryService;

    @Autowired(required = false)
    private OrganizationQueryService organizationQueryService;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private SalesPlanScItemWriteService salesPlanScItemWriteService;

    @Resource
    private BcOrderService bcOrderService;

    @Resource
    private SalesPlanOutCommonService salesPlanOutCommonService;

    @Resource
    private CustomerSaleScopeQueryService customerSaleScopeQueryService;

    @Resource
    private EpochMessageService epochMessageService;

    @Resource
    private EpochCacheService epochCacheService;

    // 按每50个一组分割
    private static final Integer MAX_NUMBER = 50;

    private static final Integer DEFAULT_PAGE_SIZE = 300;

    /**
     * 计划货品批量获取价格
     * 常规销售价+到岸价
     *
     * @param messageBody
     */
    @FacadeInvoker
    @Override
    public Result<Boolean> batchFetchPrice(String messageBody) {
        log.info("salesPlanScItemMessageConsumerImpl_batchFetchPrice_message:" + messageBody);
        if (StringUtils.isBlank(messageBody)) {
            return Result.success(null, "接受的消息为空");
        }
        BatchEditCostInsuranceFreightRequest batchEditCostInsuranceFreightRequest = null;
        try {
            batchEditCostInsuranceFreightRequest = JSONObject.parseObject(messageBody, BatchEditCostInsuranceFreightRequest.class);
            SalesPlanScItemPageQueryRequest request = new SalesPlanScItemPageQueryRequest();
            //没有指定分子公司参数，查询登录用户的所属的业务单元
            if (StringUtils.isBlank(batchEditCostInsuranceFreightRequest.getOrgBusinessUnitCode())) {
                List<OrganizationSDO> companyOrg = getCompanyOrganiztion(batchEditCostInsuranceFreightRequest.getRelatedOrganizationId(),batchEditCostInsuranceFreightRequest.getRelatedOrganizationType());
                if (CollectionUtils.isEmpty(companyOrg)) {
                    return Result.success(null, "权限不足");
                }
                List<String> orgBusinessUnitCodes = companyOrg.stream().map(OrganizationSDO::getId).distinct().filter(StringUtils::isNotBlank).collect(Collectors.toList());
                request.setOrgBusinessUnitCodes(orgBusinessUnitCodes);
            }else{
                request.setOrgBusinessUnitCodes(Lists.newArrayList(batchEditCostInsuranceFreightRequest.getOrgBusinessUnitCode()));
            }
            log.info("salesPlanScItemMessageConsumerImpl_batchFetchPrice_fetchSalesPlanScItemList_orgBusinessUnitCodes={}",request.getOrgBusinessUnitCodes());

            int page = 1;
            long start = System.currentTimeMillis();
            PageResult<List<SalesPlanScItemSDO>> pageResult = fetchSalesPlanScItemList(request, page);
            while (null != pageResult) {
                log.info("salesPlanScItemMessageConsumerImpl_batchFetchPrice_foreach_currPage={}",page);
                // 价格更新处理
                doFetchPrice(pageResult, page);
                break;
                // 已经是最后一页
//                if (pageResult.getContent().size() < page*DEFAULT_PAGE_SIZE) {
//                    break;
//                }
//                pageResult = fetchSalesPlanScItemList(request, ++page);
            }
            log.info("salesPlanScItemMessageConsumerImpl_batchFetchPrice_end_used:{}", System.currentTimeMillis() - start);
        } catch (Exception e) {
            log.error("salesPlanScItemMessageConsumerImpl_batchFetchPrice_error={}", e.getMessage());
        } finally {
            if (null != batchEditCostInsuranceFreightRequest) {
                // 执行完清理缓存
                epochCacheService.remove(BcOrderConstants.REDIS_CACHE_CODE(), Lists.newArrayList(buildRedisKey(batchEditCostInsuranceFreightRequest)));
            }
        }
        return Result.success(true, "价格更新完成");
    }

    private void doFetchPrice(PageResult<List<SalesPlanScItemSDO>> pageResult, Integer page) {
        List<SalesPlanScItemSDO> salesPlanScItemSDOList;
        try {
            // 更新价格->获取常规价, 到岸价
            salesPlanScItemSDOList = batchEditGetPrice(pageResult.getContent());
            if (CollectionUtils.isEmpty(salesPlanScItemSDOList)) {
                log.info("salesPlanScItemMessageConsumerImpl_batchFetchPrice_doFetchPrice_salesPlanScItemSDOList_no_update,page={}", page);
                // 都相等直接返回成功，不做更新处理
                return;
            }
            // 更新计划货品范围价格
            salesPlanScItemSDOList.forEach(salesPlanScItemSDO -> {
                salesPlanScItemWriteService.editSalesPlanScItem(salesPlanScItemSDO);
            });
        } catch (Exception e) {
            log.error("salesPlanScItemMessageConsumerImpl_batchFetchPrice_doFetchPrice_error_page={}, error={}", page, e);
            return;
        }
        try {
            log.info("触发月度计划汇总更新,分页数据:{}", page);
            String message = JSONObject.toJSONString(salesPlanScItemSDOList);
            boolean sendResult = epochMessageService.sendMessage("sales_plan_price_change_message", "CR_SALES_PLAN_V2", "productPlan_collect", message);
            log.info("发送触发月度计划汇总更新消息结果:{}", sendResult);
        } catch (Exception e) {
            log.error("更新价格发送消息异常", e);
        }
        // salesPlanScItemWriteService.consumePriceChange(JSONObject.toJSONString(salesPlanScItemSDOList));
    }

    private PageResult<List<SalesPlanScItemSDO>> fetchSalesPlanScItemList(SalesPlanScItemPageQueryRequest request, Integer page) {
        request.setStart((page-1)*DEFAULT_PAGE_SIZE);
        request.setLimit(DEFAULT_PAGE_SIZE);
        request.setStatus(1);
        PageResult<List<SalesPlanScItemSDO>> pageResult = salesPlanScItemRepository.pageQuerySalesPlanScItemList(request);
        if (null == pageResult || CollectionUtils.isEmpty(pageResult.getContent())) {
            return null;
        }
        return pageResult;
    }

    /**
     * 批量获取价格
     * @param salesPlanScItemSDOS
     * @return
     */
    private List<SalesPlanScItemSDO> batchEditGetPrice(List<SalesPlanScItemSDO> salesPlanScItemSDOS) {
        // 批量查询货品外部编码
        Set<String> scItemSet = salesPlanScItemSDOS.stream().map(SalesPlanScItemSDO::getScItemId).collect(Collectors.toSet());
        Map<String, ScItemSDO> scItemMap = salesPlanOutCommonService.getScItemMapByIds(scItemSet, false);
        if (MapUtils.isEmpty(scItemMap)) {
            throw new FacadeException("OTS-01-005-02-15-001");
        }
        // 查询分子公司、销售组织的outCode
        Set<String> orgSalesOrgCodeList = salesPlanScItemSDOS.stream().map(SalesPlanScItemSDO::getOrgSalesOrganizationCode).collect(Collectors.toSet());
        Set<String> orgBusinessUnitCodeList = salesPlanScItemSDOS.stream().map(SalesPlanScItemSDO::getOrgBusinessUnitCode).collect(Collectors.toSet());
        orgSalesOrgCodeList.addAll(orgBusinessUnitCodeList);
        BaselineGetOrganizationByIds2Request getOrganizationByIds2Request = BaselineGetOrganizationByIds2Request.builder()
                .ids(Lists.newArrayList(orgSalesOrgCodeList))
                .build();
        BaselineGetOrganizationByIds2Response response = baseDataService.baselineGetOrganizationByIds2(getOrganizationByIds2Request);
        if (Objects.isNull(response) || CollectionUtils.isEmpty(response.getResult())) {
            throw new FacadeException("OTS-07-005-01-16-002");
        }
        List<OrganizationSDO> organizationSDOList = response.getResult();
        Map<String, OrganizationSDO> organizationSDOMap = organizationSDOList.stream().collect(Collectors.toMap(OrganizationSDO::getId, a -> a, (a, b) -> a));
        List<OrganizationSDO> orgBusinessUnitSDOList = organizationSDOList.stream().filter(x->orgBusinessUnitCodeList.contains(x.getId())).collect(Collectors.toList());

        //查询价格 售达方  <companyOrgCode,CustomerSaleScopeSDO>
        Map<String,CustomerSaleScopeSDO> customerSaleScopeMap = batchGetCustomerSaleScopeByBizId(orgBusinessUnitSDOList);
        log.info("salesPlanScItemMessageConsumerImpl_batchEditGetPrice_getCustomerSaleScopeMap_size={},queryOrgList_size={}",customerSaleScopeMap.size(),orgBusinessUnitSDOList.size());

        //查询价格 分子公司对应的总部销售组织
        Map<String,String> superiorSalesOrgRelationMap = batchGetSuperiorSalesOrg(orgBusinessUnitCodeList);

        // 查询分销渠道
//        List<String> orgSalesChannelCodeList = salesPlanScItemSDOS.stream().map(SalesPlanScItemSDO::getOrgSalesChannelCode).distinct().collect(Collectors.toList());
//        IdQueryRequest idQueryRequest = new IdQueryRequest();
//        idQueryRequest.setIds(orgSalesChannelCodeList);
//        Result<List<OrganizationRelationSDO>> businessChannelResult = organizationQueryService.getOrgChannelRelationByOrgId(idQueryRequest);
//        SalesPlanCommonService.resultCheck(businessChannelResult, "OTS-01-003-01-16-005");
//        Map<String, OrganizationRelationSDO> businessChannelMap = businessChannelResult.getResult().stream().collect(Collectors.toMap(OrganizationRelationSDO::getOrganiztionId, a -> a, (a, b) -> a));

        List<DimensionPropertyInfoRequest> dimensionPropertyInfoRequestList = Lists.newArrayList();
        for (SalesPlanScItemSDO salesPlanScItemSDO : salesPlanScItemSDOS) {
            ScItemSDO scItemSDO = scItemMap.get(salesPlanScItemSDO.getScItemId());
            if (Objects.isNull(scItemSDO) || StringUtil.isBlank(scItemSDO.getOuterId())) {
                continue;
            }
            salesPlanScItemSDO.setOuterId(scItemSDO.getOuterId());
            // 常规价
            OrganizationSDO orgSalesOrgSDO = organizationSDOMap.get(salesPlanScItemSDO.getOrgSalesOrganizationCode());
            if (Objects.isNull(orgSalesOrgSDO) || StringUtil.isBlank(orgSalesOrgSDO.getOutCode())) {
                continue;
            }
            DimensionPropertyInfoRequest propertyInfoRequest = buildCommonSalesPrice(scItemSDO, salesPlanScItemSDO, orgSalesOrgSDO);
            if (null == propertyInfoRequest) {
                continue;
            }
            dimensionPropertyInfoRequestList.add(propertyInfoRequest);

            // 到岸价
            OrganizationSDO orgBusinessUnitSDO = organizationSDOMap.get(salesPlanScItemSDO.getOrgBusinessUnitCode());
            if (Objects.isNull(orgBusinessUnitSDO) || StringUtil.isBlank(orgBusinessUnitSDO.getBizId())) {
                continue;
            }
            CustomerSaleScopeSDO customerSaleScopeSDO = customerSaleScopeMap.get(orgBusinessUnitSDO.getBizId());
            if(Objects.isNull(customerSaleScopeSDO)){
                continue;
            }
            //查询到岸价入参总部销售组织
            String superiorSalesOrgCode = superiorSalesOrgRelationMap.get(salesPlanScItemSDO.getOrgBusinessUnitCode());

            DimensionPropertyInfoRequest propertyInfoRequest2 = buildCFIPrice(scItemSDO, customerSaleScopeSDO, superiorSalesOrgCode, salesPlanScItemSDO.getOrgBusinessChannelCode());
            if (null == propertyInfoRequest2) {
                continue;
            }
            dimensionPropertyInfoRequestList.add(propertyInfoRequest2);
        }
        if (CollectionUtils.isEmpty(dimensionPropertyInfoRequestList)) {
            return Lists.newArrayList();
        }

        // 获取分割后的集合(分批处理，一次50条)
        List<ItemPriceResponse> itemPriceResponseList = new ArrayList<>();
        long start = System.currentTimeMillis();
        int limit = countStep(dimensionPropertyInfoRequestList.size());
        List<List<DimensionPropertyInfoRequest>> splitList = Stream.iterate(0, n -> n + 1).limit(limit).parallel().map(a -> dimensionPropertyInfoRequestList.stream().skip(a * MAX_NUMBER).limit(MAX_NUMBER).parallel().collect(Collectors.toList())).collect(Collectors.toList());
        log.info("salesPlanScItemMessageConsumerImpl_batchEditGetPrice_splitList_size={}, time={}", splitList.size(), System.currentTimeMillis() - start);
        for (List<DimensionPropertyInfoRequest> dimensionPropertyInfoRequests : splitList) {
            PriceQueryRequest priceQueryRequest = new PriceQueryRequest();
            priceQueryRequest.setDimensionPropertyInfoRequestList(dimensionPropertyInfoRequests);
            Map<String, String> featuresMap = Maps.newHashMap();
            featuresMap.put("outCodeToInnerCode", "out_code_to_inner_code");
            priceQueryRequest.setFeatures(featuresMap);
            log.info("salesPlanScItemMessageConsumerImpl_batchEditGetPrice_priceQueryRequest:" + JSONObject.toJSONString(priceQueryRequest));
            Result<PriceQueryResponse> priceQueryResponseResult;
            try {
                priceQueryResponseResult = priceQueryService.batchQueryPrice(priceQueryRequest);
                log.info("salesPlanScItemMessageConsumerImpl_batchEditGetPrice_priceQueryResponseResult:" + JSONObject.toJSONString(priceQueryResponseResult));
                if (CollectionUtils.isEmpty(priceQueryResponseResult.getResult().getItemPriceResponseList())) {
                    throw new FacadeException("OTS-02-001-00-16-016");
                }
            } catch (Exception e) {
                log.error("salesPlanScItemMessageConsumerImpl_batchEditGetPrice_priceQueryResponseResult_error={}", e.getMessage());
                continue;
            }
            itemPriceResponseList.addAll(priceQueryResponseResult.getResult().getItemPriceResponseList());
        }
        if (CollectionUtils.isEmpty(itemPriceResponseList)) {
            throw new FacadeException("OTS-02-001-00-16-016");
        }
        Map<String, ItemPriceResponse> itemPriceResponseMap = itemPriceResponseList
                .stream().filter(x -> (null != x.getMoneyAmout() && x.getMoneyAmout() > 0 && null != x.getFeatures().get("priceType")))
                .collect(Collectors.toMap(x -> x.getItemId() + x.getFeatures().get("priceType"), a -> a, (a, b) -> a));
        if (MapUtils.isEmpty(itemPriceResponseMap)) {
            throw new FacadeException("OTS-02-001-00-16-016");
        }
        // 比较原价格与查询出来的价格是否相等，不相等即修改(修改更新的放一个list)
        List<SalesPlanScItemSDO> salesPlanScItemSDOList = new ArrayList<>();
        for (SalesPlanScItemSDO salesPlanScItemSDO : salesPlanScItemSDOS) {
            if (StringUtil.isNotEmpty(salesPlanScItemSDO.getOuterId())) {
                boolean costInsuranceFreightTag = false;
                boolean outboundPriceTag = false;
                log.info("获取价格赋值前计划货品:{}-常规销售价:{}-到岸价:{}", salesPlanScItemSDO.getId(), salesPlanScItemSDO.getCostInsuranceFreight(), salesPlanScItemSDO.getOutboundPrice());
                // 常规价
                ItemPriceResponse itemPriceResponse = itemPriceResponseMap.get(salesPlanScItemSDO.getOuterId() + PriceTypeEnum.ZP01.getCode());
                if (Objects.nonNull(itemPriceResponse)) {
                    // 比较原常规价是否跟查询出来的相等
                    if (!Objects.equals(salesPlanScItemSDO.getCostInsuranceFreight(), itemPriceResponse.getMoneyAmout())) {
                        // 原价和查询出来的价格不相等
                        costInsuranceFreightTag = true;
                        salesPlanScItemSDO.setCostInsuranceFreight(itemPriceResponse.getMoneyAmout());
                    }
                }
                // 到岸价
                ItemPriceResponse itemPriceResponse1 = itemPriceResponseMap.get(salesPlanScItemSDO.getOuterId() + PriceTypeEnum.ZMN1.getCode());
                if (Objects.nonNull(itemPriceResponse1)) {
                    // 比较原到岸价是否跟查询出来的相等
                    if (!Objects.equals(salesPlanScItemSDO.getOutboundPrice(), itemPriceResponse1.getMoneyAmout())) {
                        // 原价和查询出来的价格不相等
                        outboundPriceTag = true;
                        salesPlanScItemSDO.setOutboundPrice(itemPriceResponse1.getMoneyAmout());
                    }
                }
                // 只要有一个不相等及做更新
                if (costInsuranceFreightTag || outboundPriceTag) {
                    salesPlanScItemSDOList.add(salesPlanScItemSDO);
                }
                log.info("获取价格赋值后计划货品:{}-常规销售价:{}-到岸价:{}", salesPlanScItemSDO.getId(), salesPlanScItemSDO.getCostInsuranceFreight(), salesPlanScItemSDO.getOutboundPrice());
            }
        }
        return salesPlanScItemSDOList;
    }

    private DimensionPropertyInfoRequest buildCommonSalesPrice(ScItemSDO scItemSDO, SalesPlanScItemSDO salesPlanScItemSDO, OrganizationSDO orgSalesOrgSDO) {
        // 组装 货品请求数据
        MaterialInfoRequest materialInfoRequest = new MaterialInfoRequest();
        materialInfoRequest.setMaterialCode(scItemSDO.getOuterId());
        materialInfoRequest.setScItemGroupCode("11");
        // 组织 组织请求数据
        PlaceInfoRequest placeInfoRequest = new PlaceInfoRequest();
        placeInfoRequest.setSalesUnitCode(Optional.ofNullable(scItemSDO.getFeatures().get("unitName")).map(String::valueOf).orElse(null));
        placeInfoRequest.setOrgSalesOrganizationCode(orgSalesOrgSDO.getOutCode());
//        OrganizationRelationSDO organizationRelationSDO = businessChannelMap.get(salesPlanScItemSDO.getOrgSalesChannelCode());
//        if (Objects.isNull(organizationRelationSDO)) {
//            return null;
//        }
//        if (StringUtil.isBlank(organizationRelationSDO.getOutCode())) {
//            return null;
//        }
        //计划货品范围优化版本 -- 根据业务渠道获取价格
//        placeInfoRequest.setChannelCode(organizationRelationSDO.getOutCode());
        placeInfoRequest.setChannelCode(salesPlanScItemSDO.getOrgBusinessChannelCode());

        // 请求查询价格参数
        DimensionPropertyInfoRequest propertyInfoRequest = new DimensionPropertyInfoRequest();
        propertyInfoRequest.setPriceTypeId(PriceTypeEnum.ZP01.getCode());
        propertyInfoRequest.setPriceUseDate(new Date());
        propertyInfoRequest.setMaterialInfoRequest(materialInfoRequest);
        propertyInfoRequest.setPlaceInfoRequest(placeInfoRequest);
        propertyInfoRequest.setHumanInfoRequest(new HumanInfoRequest());
        return propertyInfoRequest;
    }

    private DimensionPropertyInfoRequest buildCFIPrice(ScItemSDO scItemSDO, CustomerSaleScopeSDO customerSaleScopeSDO, String superiorSalesOrgCode, String orgBusinessChannelCode) {
        // 组装 货品请求数据
        MaterialInfoRequest materialInfoRequest2 = new MaterialInfoRequest();
        // 货品
        materialInfoRequest2.setMaterialCode(scItemSDO.getOuterId());
        // 货品组
        materialInfoRequest2.setScItemGroupCode("11");

        // 组织 组织请求数据
        PlaceInfoRequest placeInfoRequest2 = new PlaceInfoRequest();
        // 销售组织
        placeInfoRequest2.setOrgSalesOrganizationCode(superiorSalesOrgCode);

        // SAP工厂
        placeInfoRequest2.setFactoryCode(Optional.ofNullable(customerSaleScopeSDO.getStoreHouse()).orElse(null));
        // 销售渠道
//        placeInfoRequest2.setSalesDepartment(Optional.ofNullable(customerSaleScopeSDO.getOutOrgSalesChannelCode()).orElse(null));
        // 业务渠道
//        placeInfoRequest2.setChannelCode("20");
        //计划货品范围版本优化 -- 根据业务渠道获取价格 原来的销售渠道不用
        placeInfoRequest2.setChannelCode(orgBusinessChannelCode);
        // 销售部门
        placeInfoRequest2.setSalesGroup(Optional.ofNullable(customerSaleScopeSDO.getOutOrgSalesDepartmentCode()).orElse(null));
        // 部门
        placeInfoRequest2.setDepartmentCode(Optional.ofNullable(customerSaleScopeSDO.getOutOrgSalesChannelCode()).orElse(null));
        // 定价区域
        placeInfoRequest2.setPriceArea(Optional.ofNullable(customerSaleScopeSDO.getSalesArea()).orElse(null));

        HumanInfoRequest humanInfoRequest2 = new HumanInfoRequest();
        // 客户
        humanInfoRequest2.setCustomerCode(Optional.ofNullable(customerSaleScopeSDO.getCustomerCode()).orElse(null));

        // 请求查询价格参数
        DimensionPropertyInfoRequest propertyInfoRequest2 = new DimensionPropertyInfoRequest();
        propertyInfoRequest2.setPriceTypeId(PriceTypeEnum.ZMN1.getCode());
        propertyInfoRequest2.setPriceUseDate(new Date());
        propertyInfoRequest2.setMaterialInfoRequest(materialInfoRequest2);
        propertyInfoRequest2.setPlaceInfoRequest(placeInfoRequest2);
        propertyInfoRequest2.setHumanInfoRequest(humanInfoRequest2);
        return propertyInfoRequest2;
    }

    /**
     * 计算切分次数
     */
    private static Integer countStep(Integer size) {
        return (size + MAX_NUMBER - 1) / MAX_NUMBER;
    }

    private List<OrganizationSDO> getCompanyOrganiztion(String orgId, String orgType) {
        List<OrganizationSDO> result = new ArrayList<>();
        if (OrganizationTypeEnum.COMPANY.getCode() < Integer.parseInt(orgType)) {
            // 登录人的角色小于分子公司的,需要层级往上找
            IdQueryRequest idQueryRequest = new IdQueryRequest();
            idQueryRequest.setId(orgId);
            idQueryRequest.setType(OrganizationTypeEnum.COMPANY.getCode());
            Result<List<com.epoch.app.crplatformenhance.sdo.OrganizationSDO>> topOrganizationList = organizationQueryService.getTopOrganizationList(idQueryRequest);
            result = topOrganizationList.getResult().stream().map(topOrganizationListResponse -> {
                OrganizationSDO organizationSDO = new OrganizationSDO();
                BeanUtils.copyProperties(topOrganizationListResponse, organizationSDO);
                return organizationSDO;
            }).collect(Collectors.toList());
        } else if (OrganizationTypeEnum.COMPANY.getCode().equals(Integer.valueOf(orgType))) {
            // 登录人为分子公司那一层，直接根据id查询名称
            BaselineGetOrganizationByIds2Request baselineGetOrganizationByIdsRequest = BaselineGetOrganizationByIds2Request.builder()
                    .ids(Lists.newArrayList(orgId))
                    .build();
            BaselineGetOrganizationByIds2Response response = baseDataService.baselineGetOrganizationByIds2(baselineGetOrganizationByIdsRequest);
            result = null != response && CollectionUtils.isNotEmpty(response.getResult()) ? response.getResult() : Lists.newArrayList();
        } else if (OrganizationTypeEnum.COMPANY.getCode() > Integer.parseInt(orgType)) {
            // 登录人大于分子分子公司级别，查询查询所有的业务单元
//            BaselineGetOrganizationByTypeRequest baselineGetOrganizationByTypeRequest = BaselineGetOrganizationByTypeRequest.builder()
//                    .type(OrganizationTypeEnum.COMPANY.getCode().toString())
//                    .build();
//            Object response = baseDataService.baselineGetOrganizationByType(baselineGetOrganizationByTypeRequest);
//            buildResponse(response, result);
            GetOrganizationByTypeResponse response = organizationQueryService.getOrganizationByType(GetOrganizationByTypeRequest.builder().type(OrganizationTypeEnum.COMPANY.getCode().toString()).build());
            if (null != response.getResult() && null != response.getResult() && CollectionUtils.isNotEmpty(response.getResult())) {
                for (com.epoch.app.crplatformenhance.sdo.OrganizationSDO x : response.getResult()) {
                    if (OrganizationTypeEnum.COMPANY.getCode().equals(x.getType())) {
                        OrganizationSDO organizationSDO = new OrganizationSDO();
                        BeanUtils.copyProperties(x, organizationSDO);
                        result.add(organizationSDO);
                    }
                }
            }
        }
        return result;
    }

    private Map<String,CustomerSaleScopeSDO> batchGetCustomerSaleScopeByBizId(List<OrganizationSDO> orgBusinessUnitSDOs) {
        if(CollectionUtils.isEmpty(orgBusinessUnitSDOs)){
            return new HashMap<>();
        }
        //查询公司获取customerCodes
        List<String> bizIdList = orgBusinessUnitSDOs.stream()
                .filter(x-> org.apache.commons.lang3.StringUtils.isNotBlank(x.getBizId()))
                .map(x->x.getBizId()).collect(Collectors.toList());
        List<CompanySDO> companySDOS = batchQueryCompany(bizIdList);
        List<String> companyCodeList = companySDOS.stream().map(x->x.getOutCode()).collect(Collectors.toList());

        //事业部6000、6004组织
        Result<QuerySuperiorSalesOrganizationResponse> groupOrgResult = organizationQueryService.queryEnterpriseGroupOrg();

        List<CustomerSaleScopeSDO> queryCustomerSaleScopes =  new ArrayList();
        //查询售达方
        QuerySaleScopeRequest querySaleScopeRequest = QuerySaleScopeRequest.newQuerySaleScopeRequestBuilder()
            .customerCodeList(companyCodeList)
                .orgSaleOrganizationCode(groupOrgResult.getResult().getEnterpriseGroup().getId())
            .itemGroup("11")
            .channelCode("20")
            .build();
        querySaleScopeRequest.setLimit(1000);
        Result<List<CustomerSaleScopeSDO>> result = customerSaleScopeQueryService.pageQuerySaleScope(querySaleScopeRequest);
        if(result != null && CollectionUtils.isNotEmpty(result.getResult())){
            result.getResult().forEach(x->{x.setOrgSalesOrganizationCode2(OrganizationConstants.ENTERPRISE_GROUP_CODE);});
            queryCustomerSaleScopes.addAll(result.getResult());
        }

        QuerySaleScopeRequest querySaleScopeRequest2 = QuerySaleScopeRequest.newQuerySaleScopeRequestBuilder()
                .customerCodeList(companyCodeList)
                .orgSaleOrganizationCode(groupOrgResult.getResult().getXinJiangCompany().getId())
                .itemGroup("11")
                .channelCode("20")
                .build();
        querySaleScopeRequest.setLimit(1000);
        Result<List<CustomerSaleScopeSDO>> result2 = customerSaleScopeQueryService.pageQuerySaleScope(querySaleScopeRequest2);
        if(result2 != null && CollectionUtils.isNotEmpty(result2.getResult())){
            result2.getResult().forEach(x->{x.setOrgSalesOrganizationCode2(OrganizationConstants.ENTERPRISE_GROUP_CODE);});
            queryCustomerSaleScopes.addAll(result2.getResult());
        }

        Map<String,CustomerSaleScopeSDO> resultMap = new HashMap<>();
        if (CollectionUtils.isEmpty(queryCustomerSaleScopes)) {
            return resultMap;
        }
        Map<String,CustomerSaleScopeSDO> customerSaleScopeMap = queryCustomerSaleScopes.stream().collect(Collectors.toMap(CustomerSaleScopeSDO::getCustomerCode, Function.identity(),(v1, v2)->v1));
        Nullable.stream(companySDOS).forEach(x->{
            CustomerSaleScopeSDO sdo = customerSaleScopeMap.get(x.getOutCode());
            if(sdo != null){
                resultMap.put(x.getId(),sdo);
            }
        });
        return resultMap;
    }

    private Map<String,String> batchGetSuperiorSalesOrg(Set<String> orgBusinessUnitCodeList) {
        if(CollectionUtils.isEmpty(orgBusinessUnitCodeList)){
            return new HashMap<>();
        }
        BatchQuerySuperiorSalesOrganizationRequest batchQuerySuperiorSalesOrganizationRequest = new BatchQuerySuperiorSalesOrganizationRequest();
        batchQuerySuperiorSalesOrganizationRequest.setOrganizationIds(Lists.newArrayList(orgBusinessUnitCodeList));
        Result<QuerySuperiorSalesOrganizationResponse> querySuperiorSalesOrganizationResponse = organizationQueryService.batchQuerySuperiorSalesOrganization(batchQuerySuperiorSalesOrganizationRequest);
        Map<String,String> relationMap = querySuperiorSalesOrganizationResponse.getResult().getRelationMap();
        return relationMap;
    }

    private List<CompanySDO> batchQueryCompany(List companyIdList){
        if(CollectionUtils.isEmpty(companyIdList)){
            return new ArrayList<>();
        }
        BatchQueryCompany2Request companyRequest = new BatchQueryCompany2Request();
        companyRequest.setIds(companyIdList);
        Result<List<CompanySDO>> result = bcOrderService.batchQueryCompany2(companyRequest);
        if(result == null || CollectionUtils.isEmpty(result.getResult())){
            return new ArrayList<>();
        }
        return result.getResult().stream().filter(x->org.apache.commons.lang3.StringUtils.isNotBlank(x.getOutCode())).collect(Collectors.toList());
    }

    private String buildRedisKey(BatchEditCostInsuranceFreightRequest request) {
        return SalesPlanConstants.getPlanScItemPriceUpdatePrefix(request.getRelatedOrganizationId() + request.getRelatedOrganizationType());
    }
}
